package com.baturu.vin.benz.service.impl;

import com.baturu.vin.benz.dto.BenzEPCPartsInfoDTO;
import com.baturu.vin.benz.dto.BenzFootnoteDTO;
import com.baturu.vin.benz.dto.BenzPartCatInfoDTO;
import com.baturu.vin.benz.dto.BenzVinInfoDTO;
import com.baturu.vin.benz.dto.footnote.*;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.OptionalDouble;
import java.util.stream.Collectors;

/**
 * @author jiangxinlei
 * @Time 2017/4/20.
 */
@Service("benzFootnotesService")
public class BenzFootnotesService {


    public FootnoteList getFootnoteList(String source, String plants, List<BenzFootnoteDTO> benzFootnoteDTOs) {
        benzFootnoteDTOs.sort(Comparator.comparing(BenzFootnoteDTO::getFtntNum).thenComparing(BenzFootnoteDTO::getSeqNum).thenComparing(BenzFootnoteDTO::getCONTINUED));
        FootnoteList footNotes = new FootnoteList();
        List<String> kbList = Lists.newArrayList("XC");
        Footnote fn2add = null;

        boolean isFnColorRev9;
        boolean isFn2ColorRev9 = false;
        for (BenzFootnoteDTO benzFootnoteDTO : benzFootnoteDTOs) {
            Footnote fn;
            if (StringUtils.isNotBlank(benzFootnoteDTO.getRevVer()) && "9".equals(benzFootnoteDTO.getRevVer())) {
                String abbrText = benzFootnoteDTO.getAbbr();
                if (abbrText != null && abbrText.length() > 0) {
                    switch (abbrText.charAt(0)) {
                        case 'E': {
                            fn = new FootnoteRev9Serial();
                            break;
                        }
                        case 'F': {
                            fn = new FootnoteRev9Color();
                            break;
                        }
                        default: {
                            fn = new FootnoteRev9Text();
                        }
                    }
                } else {
                    fn = new FootnoteRev9Text();
                }
            } else if (StringUtils.isNotBlank(benzFootnoteDTO.getFtntNum()) && benzFootnoteDTO.getFtntNum().startsWith("9")) {
                fn = new FootnoteRev8Color();
            } else {
                fn = new FootnoteRev8Text();
            }
            fn.setGroup(benzFootnoteDTO.getGroupNum());
            fn.setRevVer(benzFootnoteDTO.getRevVer());
            fn.setWISLink(StringUtils.isNotBlank(benzFootnoteDTO.getHasWisLink()));
            fn.setFNoteNum(benzFootnoteDTO.getFtntNum());
            fn.setListNum(benzFootnoteDTO.getListNum());
            fn.setAbbr(benzFootnoteDTO.getAbbr());
            fn.setText(benzFootnoteDTO.getText());
            fn.setKb(benzFootnoteDTO.getKb());
            if (StringUtils.isNotBlank(fn.getKb()) && kbList.contains(fn.getKb().toUpperCase())) {
                fn.setCKD(true);
                footNotes.setHasCkd(true);
            }
            fn.setLang(benzFootnoteDTO.getLang());
            isFnColorRev9 = fn instanceof FootnoteRev9Color;
            fn.setSeqNum(benzFootnoteDTO.getSeqNum());
            if (fn2add == null) {
                fn2add = fn;
                isFn2ColorRev9 = isFnColorRev9;
                continue;
            }
            if (!fn.getFNoteNum().equalsIgnoreCase(fn2add.getFNoteNum()) || !compareSeqNum(fn, fn2add)) {
                if (isFn2ColorRev9) {
                    if (fn2add.getEs2Codes() != null && fn2add.getEs2Codes().trim().length() > 3) {
                        footNotes.add(fn2add);
                    }
                } else {
                    footNotes.add(fn2add);
                }
                fn2add = fn;
                isFn2ColorRev9 = isFnColorRev9;
                continue;
            }
            if (isFnColorRev9 && isFn2ColorRev9) {
                if (!("N".equalsIgnoreCase(fn2add.getLang()) || "Z".equalsIgnoreCase(fn.getLang()))) {
                    continue;
                }
                if (StringUtils.isNotBlank(source)) {
                    fn2add.setCatSource(source);
                }
                ((FootnoteRev9Color) fn).setColorInfo((FootnoteRev9Color) fn2add);
                fn2add.setLang(fn.getLang());
                fn2add = fn;
                continue;
            }
            if (!("Z".equalsIgnoreCase(fn.getLang()) && "N".equalsIgnoreCase(fn2add.getLang()) || "E".equalsIgnoreCase(fn2add.getLang()))) {
                continue;
            }
            fn2add = fn;
            isFn2ColorRev9 = isFnColorRev9;
        }
        if (!(fn2add == null || fn2add instanceof FootnoteRev9Color && "N".equals(fn2add.getLang()))) {
            footNotes.add(fn2add);
        }
        footNotes.setPlants(plants);
        return footNotes;
    }

    private boolean compareSeqNum(Footnote fn, Footnote fn2) {
        int seqNo = 0;
        int seqNo2 = 0;
        int offset = 1000;
        if (fn instanceof FootnoteRev9Color && "N".equalsIgnoreCase(fn.getLang())) {
            seqNo = fn.getSeqNum() + offset;
        } else {
            seqNo = fn.getSeqNum();
        }
        if (fn2 instanceof FootnoteRev9Color && "N".equalsIgnoreCase(fn2.getLang())) {
            seqNo2 = fn2.getSeqNum() + offset;
        } else {
            seqNo2 = fn2.getSeqNum();
        }
        seqNo /= 100;
        seqNo2 /= 100;
        return seqNo == seqNo2;
    }


    public boolean validatePartByFootnote(BenzEPCPartsInfoDTO p, BenzVinInfoDTO benzVinInfoDTO, Map<String, PartInfo> catGrpFns) {
        if (p == null) {
            return true;
        }
        if (StringUtils.isBlank(p.getFootnotes())) {
            return true;
        }
        PartInfo pInfo = catGrpFns.get(p.getCatNum() + "_" + p.getGroupNum());
        FootnoteList footnotes = pInfo.getFilteredFootnotes();
        if (footnotes.size() == 0) {
            return true;
        }
        FootnoteList fnl = footnotes.getFootnotes(p.getFootnotes());
        if (fnl.size() == 0) {
            return true;
        }
        FootnoteList fnlSerial = fnl.getSerialFootnotes();
        boolean rV = true;
        if (fnlSerial != null && fnlSerial.size() != 0) {
            int partFootnoteStatus = -1;
            for (int x = 0; x < fnlSerial.size(); ++x) {
                Footnote currentFootnote = fnlSerial.get(x);
                int validStatus = currentFootnote.getValidStatus();
                if (validStatus == 0 || validStatus == 1) {
                    rV = validStatus == 0;
                    partFootnoteStatus = validStatus;
                    break;
                }
                if (validStatus == 8) {
                    partFootnoteStatus = validStatus;
                    continue;
                }
                if (partFootnoteStatus != 8) {
                    if (partFootnoteStatus != 7 && partFootnoteStatus != 6) {
                        partFootnoteStatus = validStatus;
                        continue;
                    }
                    if (validStatus == 6) {
                        partFootnoteStatus = validStatus;
                        continue;
                    }
                    if (validStatus == 7 && partFootnoteStatus != 6) {
                        partFootnoteStatus = validStatus;
                    }
                }
            }
            if (rV && partFootnoteStatus >= 3 && partFootnoteStatus <= 6) {
                rV = false;
            }
        }
        BenzPartCatInfoDTO catInfoDTO = benzVinInfoDTO.getCatInfoMapByCatNum().get(p.getCatNum());
        if (rV) {
            FootnoteList filteredfnl = this.filterFootNoteList(fnl, footnotes, benzVinInfoDTO, catInfoDTO);
            if (filteredfnl.size() <= 0) {
                rV = true;
            } else {
                FootnoteList colorfnl = filteredfnl.getFootnotesByType(FootnoteRev9Color.class);
                if (filteredfnl.nonUniqueES2(colorfnl)) {
                    p.setEs2Code(colorfnl.get(0).getEs2Codes());
                    p.setColorRemark(colorfnl.get(0).getText().trim());
                }
                rV = true;
            }
        }
        FootnoteList filteredFootnotes = pInfo.getFilteredFootnotes();
        footnoteColorFiltering(p, catInfoDTO, filteredFootnotes);
        partsColorFiltering(p, filteredFootnotes);
        return rV;
    }


    private FootnoteCodeBCountsDTO setFootnoteCodeBCounts(final FootnoteList partFnl) {
        int fnWithES2codes = 0;
        int fnWithoutES2codes = 0;
        int fnWithES2codesIndex = 0;
        int fnWithoutES2codesIndex = 0;
        for (int j = 0; j < partFnl.size(); ++j) {
            final Footnote curFootnote = partFnl.get(j);
            if (curFootnote.isColor()) {
                if (!"".equals(curFootnote.getCodeBs().trim())) {
                    fnWithES2codesIndex = j;
                    fnWithES2codes++;
                } else {
                    fnWithoutES2codesIndex = j;
                    fnWithoutES2codes++;
                }
            }
        }
        return FootnoteCodeBCountsDTO.builder()
                .fnWithES2codes(fnWithES2codes)
                .fnWithoutES2codes(fnWithoutES2codes)
                .fnWithES2codesIndex(fnWithES2codesIndex)
                .fnWithoutES2codesIndex(fnWithoutES2codesIndex)
                .build();


    }

    public void partsColorFiltering(BenzEPCPartsInfoDTO p, FootnoteList filteredFootnotes) {
        if (p.isAccessoryPart() || filteredFootnotes == null) {
            return;
        }
        if ((p.getEs2Code() != null && "".equals(p.getEs2Code().trim()))) {
            return;
        }
        FootnoteList partFnl = filteredFootnotes.getFootnotes(p.getFootnotes());
        FootnoteCodeBCountsDTO footnoteCodeBCountsDTO = setFootnoteCodeBCounts(partFnl);
        int numFnWithoutES2Codes = footnoteCodeBCountsDTO.getFnWithoutES2codes();
        int numFnWithES2Codes = footnoteCodeBCountsDTO.getFnWithES2codes();
        int fnWithES2codesIndex = footnoteCodeBCountsDTO.getFnWithES2codesIndex();
        int fnWithoutES2codesIndex = footnoteCodeBCountsDTO.getFnWithoutES2codesIndex();

        if (numFnWithoutES2Codes == 1 && numFnWithES2Codes == 1) {
            Footnote curFootnote = partFnl.get(fnWithES2codesIndex);
            p.setEs2Code(curFootnote.getEs2Codes());
            filteredFootnotes.remove(partFnl.get(fnWithoutES2codesIndex));
            return;
        }

        if (numFnWithoutES2Codes == 1 && numFnWithES2Codes == 0) {
            Footnote curFootnote = partFnl.get(fnWithoutES2codesIndex);
            p.setEs2Code(curFootnote.getEs2Codes());
            return;
        }
        if (numFnWithES2Codes == 1 && numFnWithoutES2Codes == 0) {
            Footnote curFootnote = partFnl.get(fnWithES2codesIndex);
            p.setEs2Code(curFootnote.getEs2Codes());
            return;
        }
        if (numFnWithES2Codes > 1) {
            Footnote curFootnote = partFnl.get(fnWithES2codesIndex);
            if (curFootnote.getCodeBScore() > 0.0f) {
                p.setEs2Code(curFootnote.getEs2Codes());
            }
        }

    }

    public void footnoteColorFiltering(BenzEPCPartsInfoDTO p, BenzPartCatInfoDTO catInfoDTO, FootnoteList filteredFootnotes) {
        if (StringUtils.isBlank(catInfoDTO.getSource()) || p.isAccessoryPart() || !hasColorFootnote(p)) {
            return;
        }
        if (!("D".equals(catInfoDTO.getSource()) || "M".equals(catInfoDTO.getSource()))) {
            return;
        }
        FootnoteList partFnl = filteredFootnotes.getFootnotes(p.getFootnotes());
        OptionalDouble max = partFnl.getAll().stream().filter(Footnote::isColor).mapToDouble(Footnote::getCodeBScore).max();
        float highestScore = (float) max.orElse(0);
        if (highestScore > 0.0f) {
            List<Footnote> footnotes = partFnl.getAll();
            List<Footnote> wouldRemove = footnotes.stream().filter(curFootnote -> curFootnote.isColor() && curFootnote.getCodeBScore() < highestScore).collect(Collectors.toList());
            filteredFootnotes.removeAll(wouldRemove);
        }
    }


    private boolean hasColorFootnote(BenzEPCPartsInfoDTO p) {
        String ftntnums = p.getFootnotes();
        if (ftntnums == null || "".equals(ftntnums.trim())) {
            return false;
        }
        for (int j = 0; j < ftntnums.length(); j += 3) {
            if (ftntnums.charAt(j) == '9') {
                return true;
            }
        }
        return false;
    }

    public FootnoteList filterFootNoteList(FootnoteList allFnList, FootnoteList pFootnoteList, BenzVinInfoDTO benzVinInfoDTO, BenzPartCatInfoDTO catInfoDTO) {
        if (pFootnoteList.isHasCkd()) {
            allFnList.setHasCkd(true);
        }
        if (allFnList.isHasCkd()) {
            pFootnoteList.setHasCkd(true);
        }
        if (!(allFnList.isHasCkd() && "1".contains(catInfoDTO.getClassNo()))) {
            return allFnList.getFilteredFootNoteList(pFootnoteList, benzVinInfoDTO, 0);
        }
        if (benzVinInfoDTO == null && !"FG".equalsIgnoreCase(catInfoDTO.getAggType())) {
            return allFnList.getFilteredFootNoteList(pFootnoteList, benzVinInfoDTO, 0);
        }
        String chassisNumber = benzVinInfoDTO.getChassbm() + benzVinInfoDTO.getChassIdent();
        if (chassisNumber.trim().length() > 10 && (chassisNumber.charAt(6) == '5' || chassisNumber.charAt(6) == '6')) {
            return allFnList.getFilteredFootNoteList(pFootnoteList, benzVinInfoDTO, 2);
        }
        return allFnList.getFilteredFootNoteList(pFootnoteList, benzVinInfoDTO, 1);
    }
}
